package com.shadow.disnet.netty.client;

import com.shadow.disnet.netty.ILog;
import com.shadow.disnet.netty.Life;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

public class NettyClient implements ILog, Life {
    private int PORT = 10010;
    private Bootstrap config;
    private EventLoopGroup workerGroup;
    private String IP="localhost";
    private Channel channel;
    public NettyClient() {
        config = new Bootstrap();
        ThreadFactory wf = new DefaultThreadFactory("客户端线程", false, 5);
        workerGroup = new NioEventLoopGroup(1,wf);
        config.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); //缓冲池
        config.group(workerGroup).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                info("初始化SocketChannel=%s", ch);
                ch.pipeline().addLast("encode", new StringEncoder());
                ch.pipeline().addLast("decode", new StringDecoder());
                ch.pipeline().addLast("in", new MyClientInBoundHandler());
                ch.pipeline().addLast("out", new MyClientOutBoundHandler());
            }
        });
    }

    @Override
    public Logger getLogger() {
        return LoggerFactory.getLogger(getClass());
    }

    @Override
    public void start() {
        Channel channel = config.connect(IP, PORT).addListener(f -> {
            if (f.isSuccess()) {
                info("连接服务器成功，ip=%s，port=%s", IP, PORT);
            }
        }).channel();
        this.channel = channel;
        channel.closeFuture().addListener(cf->{
            info("客户端通道关闭,优雅的关闭线程池");
            close();
        });
    }

    @Override
    public void close() {
    workerGroup.shutdownGracefully();
    }

    private void sendMessage(String msg) {
        channel.writeAndFlush(msg);
    }

    public static void main(String[] args) {
        ExecutorService exe = Executors.newCachedThreadPool();
        for (int i = 0; i < 1; i++) {
            exe.submit(NettyClient::createClient);
        }
        exe.shutdown();
    }

    private static void createClient() {
        NettyClient client = new NettyClient();
        client.start();
        Scanner scanner = new Scanner(System.in);
        while (true){
            String msg = scanner.nextLine();
            if (msg.equals("exit")){
                client.close();
                break;
            }
            client.sendMessage(msg);
        }
    }

}
